﻿Imports System.ComponentModel
Imports LSW.Win32

Namespace QQ
    <ToolboxBitmap(GetType(TabControl))> _
    Public Class QQTabControl
        Inherits TabControl
#Region "变量"
        Private _titleBackground As Drawing.Image = AssemblyHelper.GetImage("main_tab_bkg.png")
        Private _baseColor As Color = Color.White
        Private _backColor As Color = Color.Transparent
        Private _borderColor As Color = Color.White
        Private _pageColor As Color = Color.White
        ''' <summary>
        ''' 是否获取了焦点
        ''' </summary>
        Private _isFocus As Boolean = False
        ''' <summary>
        ''' 选项卡箭头区域
        ''' </summary>
        Private _btnArrowRect As Rectangle = Rectangle.Empty
#End Region

#Region "构造函数\"
        ''' <summary>
        ''' 
        ''' </summary>
        Public Sub New()
            MyBase.New()
            MyBase.SetStyle(ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.DoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.SupportsTransparentBackColor, True)
            MyBase.SizeMode = TabSizeMode.Fixed
            MyBase.ItemSize = New Size(80, 32)
            MyBase.UpdateStyles()
        End Sub
#End Region

#Region "属性"
        ''' <summary>
        ''' 
        ''' </summary>
        <DefaultValue(GetType(Color), "102, 180, 228")> _
        <CategoryAttribute("自定义属性")> _
        Public Property BaseColor() As Color
            Get
                Return Me._baseColor
            End Get
            Set(value As Color)
                Me._baseColor = value
                MyBase.Invalidate(True)
            End Set
        End Property
        ''' <summary>
        ''' 
        ''' </summary>
        <DefaultValue(GetType(Color), "234, 247, 254")> _
        <CategoryAttribute("自定义属性")> _
        Public Overrides Property BackColor() As Color
            Get
                Return Me._backColor
            End Get
            Set(value As Color)
                Me._backColor = value
                MyBase.Invalidate(True)
            End Set
        End Property
        ''' <summary>
        ''' 
        ''' </summary>
        <DefaultValue(GetType(Color), "102, 180, 228")> _
        <CategoryAttribute("自定义属性")> _
        Public Property BorderColor() As Color
            Get
                Return Me._borderColor
            End Get
            Set(value As Color)
                Me._borderColor = value
                MyBase.Invalidate(True)
            End Set
        End Property
        ''' <summary>
        ''' 
        ''' </summary>
        <Description("所有TabPage的背景颜色")> _
        <CategoryAttribute("自定义属性")> _
        Public Property PageColor() As Color
            Get
                Return Me._pageColor
            End Get
            Set(value As Color)
                Me._pageColor = value
                If Me.TabPages.Count > 0 Then
                    For i As Integer = 0 To Me.TabPages.Count - 1
                        Me.TabPages(i).BackColor = Me._pageColor
                    Next
                End If
                MyBase.Invalidate(True)
            End Set
        End Property
#End Region

#Region "Override Methods"
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnPaint(e As PaintEventArgs)
            MyBase.OnPaint(e)
            Dim g As Graphics = e.Graphics
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias

            Me.DrawBackground(g)
            Me.DrawTabPages(g)
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
            MyBase.OnMouseMove(e)
            If Not Me.DesignMode Then
                MyBase.Invalidate()
            End If
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseLeave(e As EventArgs)
            MyBase.OnMouseLeave(e)
            If Not Me.DesignMode Then
                MyBase.Invalidate()
            End If
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="e"></param>
        Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
            MyBase.OnMouseDown(e)
            If Not Me.DesignMode Then
                If e.Button = MouseButtons.Left AndAlso Me._btnArrowRect.Contains(e.Location) Then
                    Me._isFocus = True
                    MyBase.Invalidate(Me._btnArrowRect)
                End If
            End If
        End Sub
        ''' <summary>
        ''' 
        ''' </summary>
        ''' <param name="m"></param>
        Protected Overrides Sub WndProc(ByRef m As Message)
            If m.Msg <> CInt(WindowsMessage.WM_CONTEXTMENU) Then
                '0x007B鼠标右键
                MyBase.WndProc(m)
            End If
        End Sub
#End Region

#Region "Draw Methods"
        ''' <summary>
        ''' 绘制背景
        ''' </summary>
        ''' <param name="g"></param>
        Private Sub DrawBackground(g As Graphics)
            Dim width As Integer = Me.ClientRectangle.Width
            Dim height As Integer = Me.ClientRectangle.Height - Me.DisplayRectangle.Height
            Dim backColor As Color = If(Me.Enabled, Me._backColor, SystemColors.Control)
            Using brush As New SolidBrush(backColor)
                g.FillRectangle(brush, Me.ClientRectangle)
            End Using
            Dim bgRect As New Rectangle(2, 2, Me.Width - 2, Me.ItemSize.Height)
            Me.DrawImage(g, Me._titleBackground, bgRect)
            '绘制背景图
        End Sub
        ''' <summary>
        ''' 绘图
        ''' </summary>
        ''' <param name="g"></param>
        ''' <param name="image"></param>
        ''' <param name="rect"></param>
        Private Sub DrawImage(g As Graphics, image As Drawing.Image, rect As Rectangle)
            g.DrawImage(image, New Rectangle(rect.X, rect.Y, 5, rect.Height), 0, 0, 5, image.Height, _
                GraphicsUnit.Pixel)
            g.DrawImage(image, New Rectangle(rect.X + 5, rect.Y, rect.Width - 10, rect.Height), 5, 0, image.Width - 10, image.Height, _
                GraphicsUnit.Pixel)
            g.DrawImage(image, New Rectangle(rect.X + rect.Width - 5, rect.Y, 5, rect.Height), image.Width - 5, 0, 5, image.Height, _
                GraphicsUnit.Pixel)
        End Sub
        Private Sub DrawTabPages(g As Graphics)
            Using brush As New SolidBrush(Me._pageColor)
                Dim x As Integer = 2
                Dim y As Integer = Me.ItemSize.Height
                Dim width As Integer = Me.Width - 2
                Dim height As Integer = Me.Height - Me.ItemSize.Height
                g.FillRectangle(brush, x, y, width, height)
                g.DrawRectangle(New Pen(Me._borderColor), x, y, width - 1, height - 1)
            End Using
            Dim tabRect As Rectangle = Rectangle.Empty
            Dim cursorPoint As Point = Me.PointToClient(MousePosition)
            For i As Integer = 0 To MyBase.TabCount - 1
                Dim page As TabPage = Me.TabPages(i)
                tabRect = Me.GetTabRect(i)
                Dim baseColor As Color = Color.Yellow
                Dim baseTabHeaderImage As Drawing.Image = Nothing
                Dim btnArrowImage As Drawing.Image = Nothing

                If Me.SelectedIndex = i Then
                    '是否选中
                    baseTabHeaderImage = AssemblyHelper.GetImage("main_tab_check.png")
                    Dim contextMenuLocation As Point = Me.PointToScreen(New Point(Me._btnArrowRect.Left, Me._btnArrowRect.Top + Me._btnArrowRect.Height + 5))
                    Dim contextMenuStrip As ContextMenuStrip = Me.TabPages(i).ContextMenuStrip
                    If contextMenuStrip IsNot Nothing Then
                        RemoveHandler contextMenuStrip.Closed, New ToolStripDropDownClosedEventHandler(AddressOf contextMenuStrip_Closed)
                        AddHandler contextMenuStrip.Closed, New ToolStripDropDownClosedEventHandler(AddressOf contextMenuStrip_Closed)
                        If contextMenuLocation.X + contextMenuStrip.Width > Screen.PrimaryScreen.WorkingArea.Width - 20 Then
                            contextMenuLocation.X = Screen.PrimaryScreen.WorkingArea.Width - contextMenuStrip.Width - 50
                        End If
                        If tabRect.Contains(cursorPoint) Then
                            If Me._isFocus Then
                                btnArrowImage = AssemblyHelper.GetImage("main_tabbtn_down.png")
                                contextMenuStrip.Show(contextMenuLocation)
                            Else
                                btnArrowImage = AssemblyHelper.GetImage("main_tabbtn_highlight.png")
                            End If
                            Me._btnArrowRect = New Rectangle(tabRect.X + tabRect.Width - btnArrowImage.Width, tabRect.Y, btnArrowImage.Width, btnArrowImage.Height)
                        ElseIf Me._isFocus Then
                            btnArrowImage = AssemblyHelper.GetImage("main_tabbtn_down.png")
                            contextMenuStrip.Show(contextMenuLocation)
                        End If
                    End If
                ElseIf tabRect.Contains(cursorPoint) Then
                    '鼠标滑过
                    baseTabHeaderImage = AssemblyHelper.GetImage("main_tab_highlight.png")
                End If
                If baseTabHeaderImage IsNot Nothing Then
                    If Me.SelectedIndex = i Then
                        If Me.SelectedIndex = Me.TabCount - 1 Then
                            tabRect.Inflate(2, 0)
                        Else
                            tabRect.Inflate(1, 0)
                        End If
                    End If
                    Me.DrawImage(g, baseTabHeaderImage, tabRect)
                    If btnArrowImage IsNot Nothing Then
                        '当鼠标进入当前选中的的选项卡时，显示下拉按钮
                        g.DrawImage(btnArrowImage, Me._btnArrowRect)
                    End If
                End If
                TextRenderer.DrawText(g, page.Text, page.Font, tabRect, page.ForeColor)
            Next
        End Sub

#End Region

        Private Sub contextMenuStrip_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs)
            Me._isFocus = False
            MyBase.Invalidate(Me._btnArrowRect)
        End Sub
    End Class

End Namespace